
package middleware;

import kalender.backend.*;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.StringWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.DateTime;
import org.json.JSONException;
import org.json.JSONWriter;

public class Server {

    ArrayList<Session> sessionArray = new ArrayList<Session>(1);
    Socket socket;

    String clientEncoding = "UTF-8";

    public static void main (String argv[]){
        new Server();
    }

    public Server(){
        ServerSocket ssock;
        try{
            ssock = new ServerSocket(3131);
            pr("Listening");
            while(true) {
                Socket sock = ssock.accept();
                pr("===== new connection =====");
                pr(sock.getRemoteSocketAddress());

                new Server(this, sock);
                //gs.clientHandler();
            }
        }catch(IOException e){
            pr(""+e.getMessage());
        }
    }
    
    public Server(Server server, Socket socket){
        this.socket = socket;
        Command cmd = getDataFromClient(socket);
        
        if(cmd == null || cmd.cmdI == 0){
            sendError(socket, "Felaktigt kommando givet.");
        }else if(cmd.errorWrongArgs){
            sendError(socket, "Fel argument givna. Skriv: "+cmd.commandParse);
        }else{
            sendToClient(server, socket, cmd);
        }
    }

    Command getDataFromClient(Socket socket){
        try {
            InputStreamReader inputStreamRequest = new InputStreamReader(socket.getInputStream());
            boolean usesPost = false;
            int contentLength = 0;
            String get = "";
//            String userAgent = "";
            String str;
            
            StringBuilder sb = null; 
            boolean endOfHeader = false;
            int c;
             
            pr("===== HTTP HEADER =====");
            do {
            
            	sb = new StringBuilder();

            	c = inputStreamRequest.read();
            	if (c == -1) {
                    // Connection lost end of header
            		endOfHeader = true;
            	} else if (c == '\n') {
            		// Two newlines = end of header
            		endOfHeader = true;
            	} else if (c == '\r') {
            		// Two newlines = end of header
            		inputStreamRequest.read(); // read \n
            		endOfHeader = true;
            	} else {
            		while (c != '\r' && c != '\n' && c != -1) {
            			sb.append((char) c);
	            		c = inputStreamRequest.read();
	            	}
            		if (c == '\r') {
            			inputStreamRequest.read(); // read \n
            		}
            	}
            	
            	str = sb.toString();                
            
                if(str.contains("Accept-Charset:")){
                    clientEncoding = Utility.setEncoding(str);
                }else if(str.contains("POST") && str.contains("HTTP/1.1")){
                    usesPost = true;
                }else if(str.contains("GET") && str.contains("HTTP/1.1")){
                    get = str;
                }else if(str.contains("Content-Length: ")){
                    contentLength = Utility.toInt(str.split("Content-Length: ")[1]);
                }/*else if(str.contains("User-Agent: ")){
                    userAgent = getUserAgent(str.split("User-Agent: ")[1]);
                }*/
                pr("    "+str);
                
            } while (!endOfHeader);

            if(usesPost){
                pr("=====  POST DATA  =====");
                char[] cbuf = new char[contentLength];
                int read = 0;
                int a = 0;
                do {
                    a = inputStreamRequest.read(cbuf, read, contentLength - read);
                    System.out.println(a);
                    if (a != -1) 
                        read += a;
                } while (read < contentLength && a != -1);
                // System.out.println("cbuf");
                // for (char c1 : cbuf) {
                    // System.out.print(c1);
                // }
                System.out.println("post end");
                String postEncoded = Utility.arrayToString(cbuf);
                pr(postEncoded);
                return new Command(postEncoded);
            }else if(get.length() > 14){
                pr("=====  GET DATA  =====");
                String getEncoded = get.substring(6, get.length()-9);
                pr(getEncoded);
                return new Command(getEncoded);
            }
            pr("end of input stream");
            socket.shutdownInput();
            return new Command("");
        }catch(IOException e){
            pr("IOException: "+e.getMessage());
        }
        return null;
    };
    
    void sendToClient(Server server, Socket socket, Command cmd){
        if(cmd.cmdI == cmd.USR_LOGIN){
            //String uid = generateUID();//cmd.args[0]; // must presist
            Luser luser = null;
            try{
                luser = Luser.find(cmd.input[0]);
            }catch(BackendException e){
                sendError(socket, e.getMessage());
                return;
            }
            if(luser == null){
                sendError(socket, "Ogiltiga inloggningsuppgifter.");
                return;
            }
	    String MDPass = MDConverter.toMDSignature(cmd.input[1]);
	    String comp = luser.getPasswd();
	    
            if(luser.getPasswd().equals(MDPass)){
                StringWriter sw = new StringWriter();
                try{
                    JSONWriter jw = new JSONWriter(sw);
                    jw = jw.object();
                    jw = jw.key("session");
                    jw = jw.value(Utility.generateSession(server, luser.getUid()));
                    jw = jw.key("name");
                    jw = jw.value(luser.getName());
                    jw = jw.key("isAdmin");
                    jw = jw.value(Utility.isAdmin(luser));
                    jw = jw.key("greet");
                    jw = jw.value(Greeter.greet(luser.getCg_class(), luser.getCg_program(), luser.getName()));
                    jw = jw.endObject();
                }catch(JSONException e){
                    sendError(socket, "json format err");
                    return;
                }
                send(socket, sw.toString());
            }else{
                sendError(socket, "Ogiltiga inloggningsuppgifter.");
                return;
            }
        }else if(cmd.cmdI == cmd.USR_CREATE_NEW){

	    String uName="";
	    if (Utility.isAlphaNum(cmd.input[0])) {
		uName=cmd.input[0];
	    } else {
		sendError(socket, "Fel. Ditt inloggningsnamn ska vara alfanumeriskt.");
		return;
	    }
	    
	    Luser iExist = null;
	    try {
		iExist = Luser.find(uName);
	    } catch(BackendException e) {
		sendError(socket, "Kunde inte verifiera om namnet redan finns.");
		return;
	    }
	    if (iExist != null) {
		sendError(socket, "Namnet " + uName + " finns redan.");
		return;
	    }
            if(Utility.isNameReserved(uName)){
                sendError(socket, "Namnet " + uName + " reserverat.");
                return;
            }

	    String MDPass = MDConverter.toMDSignature(cmd.input[1]);
            Luser usr = new Luser();
            usr.setUname(uName);
            usr.setPasswd(MDPass);
            usr.setName(cmd.input[2]);
            try{
                usr.saveNew();
            }catch(BackendException e){
                sendError(socket, e.getMessage());
                return;
            }
            int status;
            try {
                status = usr.getUid();
            } catch (Exception e) {
                status = -1;
            }

            if (status != -1) {
                StringWriter sw = new StringWriter();
                try {
                    JSONWriter js = new JSONWriter(sw);
                    js = js.object();
                    js = js.key("uid");
                    js = js.value(status);
                    js = js.endObject();
                    send(socket, sw.toString());
                } catch(JSONException e) {
                    sendError(socket, "JSON Formatting error: status");
                    return;
                }
                } else {
                    sendError(socket,"Kunde inte skapa ny brukare i databasen.");
                    return;
                }
        }else if(cmd.input.length > 0){
            int Uid = Utility.getUid(server, cmd.input[0]);
            
            if(Uid <= 0){
                sendError(socket, "Sessionen slut. Logga in igen.");
                return;
            }

            if(cmd.cmdI == cmd.USR_METADATA_REQ){

		Luser thisLus;
                try{
                    thisLus = Luser.find(Uid);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }if(thisLus == null){
                    sendError(socket, "Ogiltigt inloggningsnamn.");
                    return;
                }
		
		List<EventType> etList = null;
                try{
                    etList = EventType.findByUser(thisLus);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }
                
		StringWriter sw = new StringWriter();
		try {
		    JSONWriter jw = new JSONWriter(sw);
		    jw = jw.array();
		    for(int i=0;i<etList.size();i++) {
			jw = jw.object();
			jw = jw.key("et_desc");
			jw = jw.value(etList.get(i).getEt_desc());
			jw = jw.endObject();
		    }
		    jw = jw.endArray();
		    send(socket, sw.toString());
		}catch(JSONException e){
		    sendError(socket, "ErrMsg: json send err");
		}
// TODO byta ut lite mot logik i base64url
	    }else if(cmd.cmdI == cmd.USR_GET_PIC_REQ){
                Luser user = null;
                LuserPic pic = null;
                if(cmd.input.length == 2 && Utility.isAdmin(Uid)){
                    try{
                        user = Luser.find(cmd.input[1]);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }if(user == null){
                        sendError(socket, "Ogiltigt inloggningsnamn.");
                        return;
                    }
                }else{
                    try{
                        user = Luser.find(Uid);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }
                    if(user == null){
                        sendError(socket, "Ogiltig inloggningsnamn.");
                        return;
                    }
                }
                try{
                    pic = LuserPic.findByUser(user);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }
                if(pic == null){
                    send(socket, "{}");
                    return;
                }
                byte[] bytes = pic.getPicture();
		int[] ints = new int[bytes.length];
		for (int i = 0; i < bytes.length; i++) {
			ints[i] = (int) bytes[i] & 0xFF;
		}

		String s = Base64url.encode(ints);

                /*
		int[] ints2 = new int[bytes.length];
		ints2 = Base64url.decode(s);

		for (int k = 0; k < bytes.length; k++) {
			if (ints[k] != ints2[k]) System.out.println("err");
		}

		byte[] bytes2 = new byte[bytes.length];
		for (int l = 0; l < bytes.length; l++) {
			bytes2[l] = (byte) ints2[l];
		}

		for (int k2 = 0; k2 < bytes.length; k2++) {
			if (bytes[k2] != bytes2[k2]) System.out.println("err2");
		}


                File file = new File("D:/hehu.jpg");
		try {
			FileOutputStream fos = new FileOutputStream(file);
			//fos.write(pic.getPicture());
			fos.write(bytes2);
			fos.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
                */

                StringWriter sw = new StringWriter();
                try{
                    JSONWriter js = new JSONWriter(sw);
                    js = js.object();
                    js = js.key("imageBase64");
                    js = js.value(s);
                    js = js.endObject();
                    send(socket, sw.toString());
                }catch(JSONException e){
                    sendError(socket, "json format error");
                }
// TODO byta ut lite mot logik i base64url
            }else if(cmd.cmdI == cmd.USR_HAS_PIC){
                Luser user = null;
                LuserPic pic = null;
                if(cmd.input.length == 2 && Utility.isAdmin(Uid)){
                    try{
                        user = Luser.find(cmd.input[1]);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }if(user == null){
                        sendError(socket, "Ogiltigt inloggningsnamn.");
                        return;
                    }
                }else{
                    try{
                        user = Luser.find(Uid);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }
                    if(user == null){
                        sendError(socket, "Ogiltig inloggningsnamn.");
                        return;
                    }
                }
                try{
                    pic = LuserPic.findByUser(user);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }
                if(pic == null){
                    StringWriter sw = new StringWriter();
                    try{
                        JSONWriter js = new JSONWriter(sw);
                        js = js.object();
                        js = js.key("haspic");
                        js = js.value(false);
                        js = js.endObject();
                        send(socket, sw.toString());
                    }catch(JSONException e){
                        sendError(socket, "json format error");
                    }
                    return;
                }
                StringWriter sw = new StringWriter();
                try{
                    JSONWriter js = new JSONWriter(sw);
                    js = js.object();
                    js = js.key("haspic");
                    js = js.value(true);
                    js = js.endObject();
                    send(socket, sw.toString());
                }catch(JSONException e){
                    sendError(socket, "json format error");
                }
            }else if(cmd.cmdI == cmd.USR_SET_PICTURE){
                        //pr(cmd.input[1].length());
                        // Leta reda pa Luser:n
                        try{
                            Luser user = Luser.find(Uid);
                            if(user == null){
                                sendError(socket, "Ogiltig inloggningsnamn.");
                                return;
                            }

                            LuserPic pic = LuserPic.findByUser(user);
                            // Lagg in ny bild
                            if(pic == null){
                                pic = new LuserPic();
                                pic.setUid(user);
                                pic.setPicture(Base64url.decodeBytes(cmd.input[1].trim()));
                                pic.saveNew();
                            // Andra en existerande bild
                            } else {
                                pic.setPicture(Base64url.decodeBytes(cmd.input[1].trim()));
                                pic.saveUpdate();
                            }
                        }catch(BackendException e){
                            sendError(socket, e.getMessage());
                            return;
                        }

                        // success
                        send(socket, "{}");

	    }else if(cmd.cmdI == cmd.USR_UPDATE_PASSWD){
				
		Luser thisLus = null;
                try{
                    thisLus = Luser.find(Uid);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }
                if(thisLus == null){
                    sendError(socket, "Ogiltigt inloggningsnamn.");
                    return;
                }

		if (!Utility.isDefault(Uid)) {
		    String newPass = cmd.input[2];
		    String oldPass = cmd.input[1];
		    String oldMDPass = MDConverter.toMDSignature(oldPass);
		    String newMDPass = MDConverter.toMDSignature(newPass);

		    if (oldMDPass.equals(thisLus.getPasswd())) {
			thisLus.setPasswd(newMDPass);
			try{
                            thisLus.saveUpdate();
                        }catch(BackendException e){
                            sendError(socket, e.getMessage());
                            return;
                        }
			send(socket, "{}");
		    } else {
			sendError(socket,"Fel pass. Operation avbruten.");
		    }
		} else {
		    sendError(socket,"Du kan inte byta pass utan att logga in.");
		}

            }else if(cmd.cmdI == cmd.USR_ADD_EVENT){
		String eDesc = cmd.input[1];
		Integer firstTime = new Integer(Utility.toInt(cmd.input[2]));
		Integer secondTime = new Integer(Utility.toInt(cmd.input[3]));
		long fT = firstTime.longValue() * 1000;
		long sT = secondTime.longValue() * 1000;
		java.util.Date dt1 = new java.util.Date(fT);
		java.util.Date dt2 = new java.util.Date(sT);
//		String period = cmd.input[4];
                String isPublic = cmd.input[4];
		String eType = cmd.input[5];
                
		
		if (!Utility.isDefault(Uid)) {
		
		    EventType thisEtype;
                    try{
                        thisEtype = EventType.find(eType);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }

                    if(thisEtype == null){
                        // hittade ingen matchande eventtype redan
			// skapa nytt
			EventType etyp = new EventType();
			etyp.setEt_desc(eType);
                        try{
                            etyp.saveNew();
                        }catch(BackendException e){
                            sendError(socket, e.getMessage());
                            return;
                        }
			thisEtype=etyp;
                    }

                    Luser luser = null;
                    try{
                        luser = Luser.find(Uid);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }if(luser == null){
                        sendError(socket, "Ogiltigt inloggningsnamn.");
                        return;
                    }

                    Event ev = new Event();
                    //ev.setPtype(per);
                    ev.setUid(luser);
                    ev.setE_desc(eDesc);
                    ev.setStart_ts(dt1);
                    ev.setStop_ts(dt2);
                    ev.setPubshare(Utility.toBoolean(isPublic));
                    ev.setEtype(thisEtype);
                    try{
                        ev.saveNew();
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }

                    /*Luser thisUsr = Luser.find(Uid);

                    UserType ut = new UserType();
                    ut.setUid(thisUsr);
                    ut.setEid(ev);
                    ut.setEtype(thisEtype);
                    ut.saveNew();*/

                    send(socket, "{}");
		} else {
		    sendError(socket, "Du kan inte skapa nya poster utan att logga in.");
		}
		
            }else if(cmd.cmdI == cmd.USR_DELETE_EVENT){

		// far bara eid fran kommandot

		int eid = Utility.toInt(cmd.input[1]);
		Luser thisLus;
                try{
                    thisLus = Luser.find(Uid);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }if(thisLus == null){
                    sendError(socket, "Ogiltigt inloggningsnamn.");
                    return;
                }
                try{
                    Event.delete(eid);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }
                send(socket, "{}");

            }else if(cmd.cmdI == cmd.USR_EVENT_RANGE){

		Integer firstTime = new Integer(Utility.toInt(cmd.input[1]));
		Integer secondTime = new Integer(Utility.toInt(cmd.input[2]));
		long fT = firstTime.longValue() * 1000;
		long sT = secondTime.longValue() * 1000;
		java.util.Date dt1 = new java.util.Date(fT);
		java.util.Date dt2 = new java.util.Date(sT);
	       
//		SortedMap<Event, EventType> events;
		List<Event> events;
		if (Utility.isDefault(Uid)) { // om default luser
                    try{
                        events = Event.findPublicByDate(dt1, dt2);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }
		} else {
		    try{
                        events = Event.findByUserAndDate(Luser.find(Uid), dt1, dt2);
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }
		}
		if(events.size() > 0){
		    StringWriter sw = new StringWriter();
		    try {
                        JSONWriter js = new JSONWriter(sw);
                        js = js.array();
                        for(Event e : events){
                            js = js.object();
                            js = js.key("eid");
                            js = js.value(e.getEid());
			    js = js.key("e_desc");
                            js = js.value(e.getE_desc());
                            js = js.key("start");
                            js = js.value(e.getStart_ts().getTime());
			    js = js.key("stop");
                            js = js.value(e.getStop_ts().getTime());
                            js = js.key("pubshare");
                            js = js.value(e.getPubshare());
			    js = js.key("etype");
                            js = js.value(e.getEtype().getEt_desc());
                            js = js.key("name");
                            js = js.value(e.getUid().getName());
			    js = js.endObject();
                        }
                        js = js.endArray();
                        //pr(sw.toString());
                        send(socket, sw.toString());
		    } catch (JSONException e) {
			sendError(socket, "ERR: json format error");
			//e.printStackTrace();
		    }
		}else{
		    send(socket, "[]");
		}
		
            }else if(cmd.cmdI == cmd.GET_DAY){
                DateTime dt1=null;
                DateTime dt2=null;

                try{
                    dt1 = new DateTime(Utility.toInt(cmd.input[1]), Utility.toInt(cmd.input[2]), Utility.toInt(cmd.input[3]), 0, 0, 0, 0);
                    dt2 = new DateTime(Utility.toInt(cmd.input[1]), Utility.toInt(cmd.input[2]), Utility.toInt(cmd.input[3]), 0, 0, 0, 0);
                }catch(org.joda.time.IllegalFieldValueException e){
                    sendError(socket, "Felaktigt datum.");
                    return;
                }
                dt2 = dt2.plusDays(1);
		List<Event> events;
		if (Utility.isDefault(Uid)) {
                    try{
                        events = Event.findPublicByDate(dt1.toDate(), dt2.toDate());
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }
		} else {
		    try{
                        events = Event.findByUserAndDate(Luser.find(Uid), dt1.toDate(), dt2.toDate());
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }
		}

		if(events.size() > 0){
                    StringWriter sw = new StringWriter();
                    try {
                        JSONWriter js = new JSONWriter(sw);
                        js = js.array();
                        for(Event e : events){
                            js = js.object();
                            js = js.key("eid");
                            js = js.value(e.getEid());
                            js = js.key("start");
                            js = js.value(e.getStart_ts().getTime());
                            js = js.key("stop");
                            js = js.value(e.getStop_ts().getTime());
                            js = js.key("e_desc");
                            js = js.value(e.getE_desc());
                            js = js.key("etype");
                            js = js.value(e.getEtype().getEt_desc());
                            js = js.endObject();
                        }
                        js = js.endArray();
                        //pr(sw.toString());
                        send(socket, sw.toString());
                    } catch (JSONException e) {
                        sendError(socket, "ERR: json format error");
                    }
                }else{
                    send(socket, "[]");
                }
            }else if(cmd.cmdI == cmd.ADMIN_DELETE_USER){
                
		// hard-coded: admin is uname "admin" and has uid = 2
		
		int del_uid = Utility.toInt(cmd.input[1]);

		Luser luser = null;
                try{
                    luser = Luser.find(del_uid);
                }catch(BackendException e){
                    sendError(socket, e.getMessage());
                    return;
                }if(luser == null){
                    send(socket, "{}");
                    return;
                }

                
		if (Utility.isAdmin(Uid)) {
		    if (!((Utility.isDefault(del_uid)) || (Utility.isAdmin(del_uid)))) {
			List<Event> events = null;
                        try{
                            events = Event.findByUser(luser);
                        }catch(BackendException e){
                            sendError(socket, e.getMessage());
                            return;
                        }
                        for(Event event : events){
                            try{
                                Event.delete(event.getEid());
                            }catch(BackendException e){
                                sendError(socket, e.getMessage());
                                return;
                            }
                        }
			LuserPic lp = null;
			try {
			    lp = LuserPic.findByUser(luser);
			} catch(BackendException e){
			    sendError(socket, e.getMessage());
			    return;
			}
			if (lp != null) {
			    try {
				LuserPic.delete(lp.getUid().getUid());
			    } catch(BackendException e){
				sendError(socket, e.getMessage());
				return;
			    }
			}

			try{
                            // Ta bort alla sessioner forst
                            Utility.deleteAllSessionWithUID(this, del_uid);
                            Luser.delete(del_uid);
                        }catch(BackendException e){
                            sendError(socket, e.getMessage());
                            return;
                        }
			send(socket, "{}");
		    } else {
			sendError(socket, "Kan inte ta bort admin eller default.");
		    }
		} else {
		    sendError(socket, "admin privilege violation attempt. logged.");
		}

	    }else if(cmd.cmdI == cmd.ADMIN_LIST_USERS){

		if (Utility.isAdmin(Uid)) {
		    List<Luser> usList = null;
                    try{
                        usList = Luser.findAll();
                    }catch(BackendException e){
                        sendError(socket, e.getMessage());
                        return;
                    }
		    StringWriter sw = new StringWriter();
		    try {
			JSONWriter jw = new JSONWriter(sw);
			jw = jw.array();
			for(int i=0;i<usList.size();i++) {
			    jw = jw.object();
			    jw = jw.key("uid");
			    jw = jw.value(usList.get(i).getUid());
			    jw = jw.key("uname");
			    jw = jw.value(usList.get(i).getUname());
			    jw = jw.key("name");
			    jw = jw.value(usList.get(i).getName());
			    jw = jw.endObject();
			}
			jw = jw.endArray();
			send(socket, sw.toString());
		    }catch(JSONException e){
			sendError(socket, "ERR: json format err");
		    }
		} else {
		    sendError(socket, "admin privilege violation attempt. logged.");
		}

            }else if(cmd.cmdI == cmd.USR_SUICIDE){
                Utility.deleteAllSessionWithUID(server, Uid);
                send(socket, "{}");
            }else{
                sendError(socket, "Odefinierat kommando.");
            }
        }else{
            pr("invalid command");
            sendError(socket, "Felaktigt kommando.");
        }
    }
    
    void sendError(Socket socket, String error){
        String equal = "=";
//        if(isAndroid(cmd.userAgent))
//            equal=AndroidEqual;
        StringWriter sw = new StringWriter();
        try{
            JSONWriter jw = new JSONWriter(sw);
            jw = jw.object();
            jw = jw.key("error");
            jw = jw.value(error);
            jw = jw.endObject();
        }catch(JSONException e){
            sendError(socket, "ERR: json format err");
        }
        send(socket, sw.toString());
        //send(socket, "Error"+equal+error, cmd);
    }

    void send(Socket socket, String response){
        send(socket, new String[]{response});
    }

    void send(Socket socket, String[] response){
        String and = "&", equal = "=";
//        if(isAndroid(cmd.userAgent)){
//            and = AndroidAnd;
//            equal = AndroidEqual;
//        }
        try{
            PrintStream pstream = new PrintStream(socket.getOutputStream(), true, clientEncoding);
//            PrintStream pstream = new PrintStream(socket.getOutputStream());
            pstream.print("HTTP/1.1 200 OK\n");
            pstream.print("Content-Type: text/html; charset=utf-8\n");
//            pstream.println("Set-Cookie: SESSIONID=" + mySession);
            pstream.print("\n");

            pr("===== sending Data to client =====");
            for(int i = 0; i < response.length; i++){
                pstream.print(response[i]);
                pr(response[i]);
            }

            pstream.close();
            pr("===== Dropping client =====\n\n");
            socket.close();
        }catch(IOException e){
            pr(e.getMessage());
        }
    }
    
    void pr(Object o){
        String debug = System.getProperty("debug");
        if (debug != null && debug.equals("1")) {
            System.out.println(""+o);
        }
    }
}